import type { CheckboxValueType } from 'element-plus'

import { useRequest } from '@/hooks/useRequest'

import Storage from '@/utils/Storage'
import { DEFAULT_MIXING_STATION_ID_KEY } from '@/utils/constant'

import {
  getTableDataRequest,
  updateUserInfoRequest,
  updateUserStation,
  updateOnlineStatusRequest,
  bindUserCustomerRequest,
  deleteUserCustomerRequest,
  getUserCustomerDataRequest,
  getBindingAllowCustomerRequest,
  bindUserStationRequest,
  deleteUserStationRequest,
  getUserStationDataRequest,
  getAllowStationDataRequest,
  bindUserCarRequest,
  deleteUserCarRequest,
  getUserCarDataRequest,
  getBindingAllowCarRequest
} from '@/api/applet/index'

import { getMixingStationList } from '@/api/customer/customer'
import type { MixingStationData } from '@/api/customer/customer'

import type {
  SearchParams,
  AppletUserData,
  BindingCar,
  AllowBindStation,
  BindStation,
  BindCustomer,
  AllowBindCustomer
} from '@/api/applet/index'

// 增强列表数据
type EnhanceTableData<T> = T & { checked: boolean }

// table 功能
export function useTable() {
  const queryFormRef = ref(ElForm)

  const queryParams = reactive<Partial<SearchParams>>({ timeType: 1, nowPage: 1, pageSize: 10 })

  const total = ref(0)
  const tableData = ref<AppletUserData[]>([])
  const { run, loading } = useRequest(getTableDataRequest, {
    manual: true,
    defaultParams: [queryParams],
    onSuccess({ result }) {
      const { records, total: totalRes } = result
      total.value = totalRes
      tableData.value = records
    }
  })

  const handleQuery = () => {
    run(queryParams)
  }

  const handlePaginationChange = (page: number, pageSize: number) => {
    queryParams.nowPage = page
    queryParams.pageSize = pageSize
    handleQuery()
  }

  const handleResetQuery = () => {
    queryFormRef.value.resetFields()
    queryParams.timeType = 1
    queryParams.startTime = ''
    queryParams.endTime = ''
    handleQuery()
  }
  return {
    queryFormRef,
    queryParams,
    total,
    loading,
    tableData,
    handleQuery,
    handlePaginationChange,
    handleResetQuery
  }
}

// 编辑
export function useEdit(refreshCb) {
  const editDialogVisible = ref(false)
  const editFormRef = ref()
  const editForm = reactive<Pick<AppletUserData, 'id' | 'phone' | 'accountType' | 'realName' | 'enableStatus'>>({
    id: '',
    phone: '',
    accountType: null,
    realName: '',
    enableStatus: null
  })

  const editFormRules = {
    accountType: [{ required: true, message: '请选择账号类型', trigger: 'change' }],
    enableStatus: [{ required: true, message: '请选择启用状态', trigger: 'blur' }]
  }
  const editLoading = ref(false)
  const handleEdit = (row: AppletUserData) => {
    Object.keys(editForm).forEach(k => {
      editForm[k] = row[k]
    })
    editDialogVisible.value = true
  }

  const handleEditCommitClick = async () => {
    editFormRef.value?.validate((valid: boolean) => {
      if (valid) {
        editLoading.value = true
        updateUserInfoRequest(editForm)
          .then(() => {
            ElMessage.success('编辑成功')
            editDialogVisible.value = false
            refreshCb()
          })
          .finally(() => {
            editLoading.value = false
          })
      }
    })
  }
  return {
    editDialogVisible,
    editFormRef,
    editForm,
    editFormRules,
    editLoading,
    handleEdit,
    handleEditCommitClick
  }
}

// 切换搅拌站
export function useSwitchStation(refreshCb) {
  const switchStationVisible = ref(false)
  const switchStationFormRef = ref()

  const stationForm = reactive({
    id: '',
    mixingStationNumber: ''
  })

  const switchStationLoading = ref(false)

  const stationFormRules = {
    mixingStationNumber: [{ required: true, message: '请选择搅拌站', trigger: 'change' }]
  }
  const stationOptions = ref<MixingStationData[]>([])

  const handleSwitchStation = (row: AppletUserData) => {
    stationForm.id = row.id //  小程序用户 id
    stationForm.mixingStationNumber = row.currentStationNumber
    if (!stationOptions.value || !stationOptions.value.length) {
      getStateOptions()
    }
    switchStationLoading.value = false
    switchStationVisible.value = true
  }

  async function getStateOptions() {
    // 切换站点不需要权限过滤
    const { result } = await getMixingStationList({ authFilter: false })
    stationOptions.value = result
  }

  const handleSwitchCommit = () => {
    switchStationFormRef.value?.validate((valid: boolean) => {
      if (valid) {
        updateUserStation(stationForm)
          .then(() => {
            ElMessage.success('切换成功')
            switchStationVisible.value = false
            refreshCb()
          })
          .finally(() => {
            switchStationLoading.value = false
          })
      }
    })
  }

  return {
    switchStationVisible,
    switchStationFormRef,
    stationForm,
    stationOptions,
    stationFormRules,
    switchStationLoading,
    handleSwitchStation,
    handleSwitchCommit
  }
}

// 车辆上线/下线
export function useOnlineUpdate() {
  const onlineOpType = ref<0 | 1>(1) // 上线状态：0.下线 1.上线
  const onlineForm = reactive({
    id: '', // 小程序用户 id
    carNumber: '',
    carId: ''
  })
  const handleUpdateOnlineClick = async (row: AppletUserData) => {
    // 没有当前绑定车辆
    if (!row.onlineCarId) {
      ElMessage.error('当前司机还未上线过车辆，首次上线需在小程序端操作')
      return false
    }
    // driverIsOnline === 1 在线，执行下线操作
    onlineOpType.value = row.driverIsOnline === 1 ? 0 : 1
    onlineForm.id = row.id
    onlineForm.carId = row.onlineCarId
    onlineForm.carNumber = row.onlineCarNumber || ''

    const title = `是否${row.driverIsOnline === 1 ? '下线' : '上线'}车辆${onlineForm.carNumber}`

    ElMessageBox.confirm(title, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(async () => {
        const { result } = await commitAction()
        // 排队中车辆下线需要二次提醒
        if ((result as string).includes('排队中#')) {
          const title = result.replace('排队中#', '')
          ElMessageBox.confirm(title, '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(async () => {
            // 再次请求
            await commitAction({ forcedOffline: true })
            ElMessage.success(onlineOpType.value === 0 ? '下线' : '上线' + '操作成功')
            row.driverIsOnline = onlineOpType.value
            // handleQuery()
          })
          return false
        }

        ElMessage.success(onlineOpType.value === 0 ? '下线' : '上线' + '操作成功')
        row.driverIsOnline = onlineOpType.value
        // handleQuery()
        return false
      })
      .catch(() => {
        return false
      })
  }

  function commitAction(params = {}) {
    return updateOnlineStatusRequest({
      id: onlineForm.id,
      carId: onlineForm.carId,
      onlineStatus: onlineOpType.value,
      ...params
    })
  }

  return {
    onlineOpType,
    onlineForm,
    handleUpdateOnlineClick
  }
}

type PureFunction = (...args: any[]) => any
interface BindStrategy {
  text: string // 类型中文名
  promptKey: string // 已绑定搜索输入提示
  btnText: string // 列表操作名
  add: PureFunction // 新增方法
  delete: PureFunction // 删除方法
  list: PureFunction // 查询已绑定列表方法
  addList: PureFunction // 查询可新增绑定列表方法
  tableFilter: (row: any, keyWords: string) => boolean // 已绑定列表，前端搜索方法
  submitDataTransform: (row: any) => any // 新增绑定，提取参数方法
}

// 绑定操作
export function useBind(cb: () => void) {
  // accountType: 1 | 2 | 3 // 账号类型：1.司机 2.客户 3.技术员
  // 绑定操作：三个账号类型分别对应不同的绑定内容，司机绑定车辆、客户绑定客户信息、技术员绑定站点 -->
  const bindStrategy: Record<number, BindStrategy> = {
    1: {
      text: '车辆',
      promptKey: '车牌号码',
      btnText: '绑定车辆',
      add: bindUserCarRequest,
      delete: deleteUserCarRequest,
      list: getUserCarDataRequest,
      addList: getBindingAllowCarRequest,
      // 已绑定项目筛选
      tableFilter: (row: BindingCar, keyWords: string) => {
        if (row.carNumber) {
          return row.carNumber.includes(keyWords)
        }
        return false
      },
      submitDataTransform: (row: EnhanceTableData<BindingCar>) => ({ carId: row.id })
    },
    2: {
      text: '客户',
      promptKey: '客户名称',
      btnText: '绑定客户信息',
      add: bindUserCustomerRequest,
      delete: deleteUserCustomerRequest,
      list: getUserCustomerDataRequest,
      addList: getBindingAllowCustomerRequest,
      tableFilter: (row: BindCustomer, keyWords: string) => {
        if (row.customerName) {
          return row.customerName.includes(keyWords)
        }
        return false
      },
      submitDataTransform: (row: EnhanceTableData<AllowBindCustomer>): BindCustomer => ({
        customerName: row.name,
        customerCode: row.code
      })
    },
    3: {
      text: '搅拌站',
      promptKey: '搅拌站名称',
      btnText: '绑定站点',
      add: bindUserStationRequest,
      delete: deleteUserStationRequest,
      list: getUserStationDataRequest,
      addList: getAllowStationDataRequest,
      tableFilter: (row: BindStation, keyWords: string) => {
        if (row.mixingStationName) {
          return row.mixingStationName.includes(keyWords)
        }
        return false
      },
      submitDataTransform: (row: EnhanceTableData<AllowBindStation>): BindStation => ({
        mixingStationNumber: row.number
      })
    }
  }
  // 获取绑定按钮标题
  const getBtnText = type => {
    return bindStrategy[type]?.btnText || ''
  }

  const getMethod = (type, methodType) => {
    return bindStrategy[type][methodType]
  }

  let appletUserId = '' // 小程序用户 id
  const bindType = ref(null) // 保存绑定操作类型

  const getPrompt = () => {
    return bindStrategy[bindType.value]?.promptKey || ''
  }

  const bindDialogVisible = ref(false)
  const bindTableLoading = ref(false)
  const originTableData = ref([]) // 原始列表数据
  const bindListKeyWord = ref('')
  // 关键词过滤后数据
  const bindTableData = computed(() =>
    originTableData.value.filter(row => {
      if (!bindType.value || !bindListKeyWord.value) {
        return originTableData.value
      }
      return getMethod(bindType.value, 'tableFilter')(row, bindListKeyWord.value)
    })
  ) // 绑定车辆列表
  const bindTypeText = ref('')
  // 点击绑定操作
  const handleBind = (row: AppletUserData) => {
    bindType.value = row.accountType // 保存操作类型
    appletUserId = row.id // 保存小程序用户 id
    bindTypeText.value = bindStrategy[bindType.value].text // 不同类型需要切换的 title
    bindListKeyWord.value = ''
    getBindList()
    bindDialogVisible.value = true
  }

  // 删除已绑定
  const handleBindDelete = (row: any) => {
    ElMessageBox.confirm('确定删除吗?', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(async () => {
      // 获取删除接口
      const method = getMethod(bindType.value, 'delete')
      await method({ id: row.id })
      ElMessage.success('删除成功')
      getBindList()
      cb()
    })
  }
  // 新增绑定
  const bindAddDialogVisible = ref(false)
  const bindAddTableLoading = ref(false)
  const bindAddPag = reactive({
    nowPage: 1,
    pageSize: 10,
    total: 0
  })
  const bindAddTable = ref([])
  const bindKeyWord = ref('')
  // 可绑定元素查询
  const handleBoundQuery = async () => {
    bindAddTableLoading.value = true
    try {
      // 获取可绑定接口
      const method = getMethod(bindType.value, 'addList')
      const { result } = await method({
        searchKey: bindKeyWord.value,
        appletUserId,
        nowPage: bindAddPag.nowPage,
        pageSize: bindAddPag.pageSize
      })
      bindAddTable.value =
        result.records?.map(item => {
          return { ...item, checked: false }
        }) || []
      bindAddPag.total = result.total
    } finally {
      bindAddTableLoading.value = false
    }
  }

  // 单选选中值
  let prevSelection = null
  const onBindAddSelected = (val: CheckboxValueType, row: any) => {
    // 已选中清空选中
    prevSelection && (prevSelection.checked = false)
    // 多选选中值
    prevSelection = null
    if (val) {
      prevSelection = row
    }
  }
  // 新增弹框初始化
  const handleBindAdd = () => {
    bindAddTable.value = []
    bindAddDialogVisible.value = true
    bindAddPag.nowPage = 1
    bindAddPag.pageSize = 10
    bindAddPag.total = 0
    bindKeyWord.value = ''
    handleBoundQuery()
  }
  const bindAddLoading = ref(false)

  // 新增绑定提交
  const handleBindAddSubmit = async () => {
    if (!prevSelection) {
      ElMessage.error('请选择绑定' + getBtnText(bindType.value))
      return
    }
    // 获取绑定接口
    const method = getMethod(bindType.value, 'add')
    // 获取提交额外参数转化方法
    const transFn = getMethod(bindType.value, 'submitDataTransform')
    bindAddLoading.value = true
    try {
      await method({
        ...transFn(prevSelection),
        appletUserId
      })
      bindAddDialogVisible.value = false
      getBindList()
      cb()
    } finally {
      bindAddLoading.value = false
    }
  }

  const handleBindPagChange = (page: number, pageSize: number) => {
    bindAddPag.nowPage = page
    bindAddPag.pageSize = pageSize
    handleBoundQuery()
  }

  function getBindList() {
    bindTableLoading.value = true
    originTableData.value = []
    // 获取已绑定接口
    const method = getMethod(bindType.value, 'list')
    method({ appletUserId })
      .then(({ result }) => {
        originTableData.value = result
      })
      .finally(() => {
        bindTableLoading.value = false
      })
  }

  return {
    bindType,
    getBtnText,
    getPrompt,
    handleBind,
    bindDialogVisible,
    bindListKeyWord,
    bindTableLoading,
    bindTableData,
    bindTypeText,
    handleBindDelete,
    bindAddDialogVisible,
    handleBindAdd,
    bindKeyWord,
    bindAddTableLoading,
    bindAddLoading,
    bindAddTable,
    bindAddPag,
    handleBoundQuery,
    handleBindPagChange,
    onBindAddSelected,
    handleBindAddSubmit
  }
}

// 获取搅拌站信息，设置默认选中
export function useStation(queryParams: Partial<SearchParams>, refresh: () => void) {
  const { data: stationRes } = useRequest(getMixingStationList, {
    onSuccess({ result }) {
      if (result && result.length) {
        let defaultMixingStation: MixingStationData = null
        const defaultMixingStationId = Storage.getStorage(DEFAULT_MIXING_STATION_ID_KEY)

        // 先从本地缓存匹配搅拌站数据；如果能找到数据，则说明该用户有本地缓存搅拌站的权限
        if (defaultMixingStationId) {
          defaultMixingStation = result.find(item => item.id === defaultMixingStationId)
        }

        // 如果无缓存或者无法匹配到数据；则默认取第一个数据并重新设置缓存
        if (!defaultMixingStation) {
          defaultMixingStation = result[0]
          Storage.setStorage(DEFAULT_MIXING_STATION_ID_KEY, defaultMixingStation.id)
        }

        // 成功获取站点列表后，执行选中默认站点刷新列表
        queryParams.carStationNumber = defaultMixingStation.number
      }
    },
    onAfter() {
      refresh()
    }
  })

  const stationList = computed(() => stationRes.value?.result || [])
  return {
    stationList
  }
}
